home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / ulibnt.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  29KB  |  840 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    u l i b n t . c                                                 */
  3. /*                                                                    */
  4. /*    Windows NT serial port support for UUCICO                       */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) David M. Watt 1993, All Rights Reserved   */
  9. /*--------------------------------------------------------------------*/
  10.  
  11. /*--------------------------------------------------------------------*/
  12. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  13. /*    Wonderworks.                                                    */
  14. /*                                                                    */
  15. /*    All rights reserved except those explicitly granted by the      */
  16. /*    UUPC/extended license agreement.                                */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*--------------------------------------------------------------------*/
  20. /*                          RCS Information                           */
  21. /*--------------------------------------------------------------------*/
  22.  
  23. /*
  24.  *       $Id: ulibnt.c 1.6 1993/10/03 22:09:09 ahd Exp $
  25.  *       $Log: ulibnt.c $
  26.  * Revision 1.6  1993/10/03  22:09:09  ahd
  27.  * Use unsigned long to display speed
  28.  *
  29.  * Revision 1.5  1993/09/26  03:32:27  dmwatt
  30.  * Use Standard Windows NT error message module
  31.  *
  32.  * Revision 1.4  1993/09/25  03:07:56  ahd
  33.  * Add standard Windows NT error message calls
  34.  *
  35.  * Revision 1.3  1993/09/21  01:42:13  ahd
  36.  * Use standard MAXPACK limit for save buffer size
  37.  *
  38.  * Revision 1.2  1993/09/20  04:50:57  ahd
  39.  * Break out of ULIBOS2.C
  40.  *
  41.  * Revision 1.14  1993/05/30  15:25:50  ahd
  42.  * Multiple driver support
  43.  *
  44.  * Revision 1.13  1993/05/30  00:08:03  ahd
  45.  * Multiple communications driver support
  46.  * Delete trace functions
  47.  *
  48.  * Revision 1.12  1993/05/09  03:41:47  ahd
  49.  * Make swrite accept constant input strings
  50.  *
  51.  * Revision 1.11  1993/04/11  00:34:11  ahd
  52.  * Global edits for year, TEXT, etc.
  53.  *
  54.  * Revision 1.10  1993/04/10  21:25:16  dmwatt
  55.  * Add Windows NT support
  56.  *
  57.  * Revision 1.9  1993/04/05  04:32:19  ahd
  58.  * Additional traps for modem dropping out
  59.  *
  60.  * Revision 1.8  1993/04/04  04:57:01  ahd
  61.  * Add configurable OS/2 priority values
  62.  *
  63.  * Revision 1.7  1992/12/30  13:02:55  dmwatt
  64.  * Dual path for Windows NT and OS/2
  65.  *
  66.  * Revision 1.6  1992/12/11  12:45:11  ahd
  67.  * Correct RTS handshake
  68.  *
  69.  * Revision 1.5  1992/12/04  01:00:27  ahd
  70.  * Add copyright message, reblock other comments
  71.  *
  72.  * Revision 1.4  1992/11/29  22:09:10  ahd
  73.  * Add new define for BC++ OS/2 build
  74.  *
  75.  * Revision 1.3  1992/11/19  03:00:39  ahd
  76.  * drop rcsid
  77.  *
  78.  * Revision 1.2  1992/11/15  20:11:48  ahd
  79.  * Add English display of modem status and error bits
  80.  *
  81.  */
  82.  
  83. /*--------------------------------------------------------------------*/
  84. /*                        System include files                        */
  85. /*--------------------------------------------------------------------*/
  86.  
  87. #include <stdlib.h>
  88. #include <stdio.h>
  89. #include <string.h>
  90. #include <fcntl.h>
  91. #include <io.h>
  92. #include <time.h>
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*                      Windows NT include files                      */
  96. /*--------------------------------------------------------------------*/
  97.  
  98. #include <windows.h>
  99. #include <limits.h>
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*                    UUPC/extended include files                     */
  103. /*--------------------------------------------------------------------*/
  104.  
  105. #include "lib.h"
  106. #include "ulib.h"
  107. #include "ssleep.h"
  108. #include "catcher.h"
  109.  
  110. #include "commlib.h"
  111. #include "pnterr.h"
  112.  
  113. /*--------------------------------------------------------------------*/
  114. /*                          Global variables                          */
  115. /*--------------------------------------------------------------------*/
  116.  
  117. currentfile();
  118.  
  119. static boolean   carrierdetect = FALSE;  /* Modem is not connected     */
  120.  
  121. static boolean hangupNeeded = FALSE;
  122. static boolean console = FALSE;
  123.  
  124. static currentSpeed = 0;
  125.  
  126. #define FAR_NULL ((PVOID) 0L)
  127.  
  128. /*--------------------------------------------------------------------*/
  129. /*           Definitions of control structures for DOS API            */
  130. /*--------------------------------------------------------------------*/
  131.  
  132. static HANDLE hCom;
  133. static COMMTIMEOUTS CommTimeout;
  134. static DCB dcb;
  135.  
  136. static BYTE com_status;
  137. static USHORT com_error;
  138.  
  139. static USHORT usPrevPriority;
  140.  
  141. static void ShowError( const USHORT status );
  142.  
  143. static void ShowModem( const DWORD status );
  144.  
  145. /*--------------------------------------------------------------------*/
  146. /*    n o p e n l i n e                                               */
  147. /*                                                                    */
  148. /*    Open the serial port for I/O                                    */
  149. /*--------------------------------------------------------------------*/
  150.  
  151. int nopenline(char *name, BPS baud, const boolean direct )
  152. {
  153.    DWORD dwError;
  154.    BOOL rc;
  155.  
  156.    if (portActive)              /* Was the port already active?     ahd   */
  157.       closeline();               /* Yes --> Shutdown it before open  ahd   */
  158.  
  159. #ifdef UDEBUG
  160.    printmsg(15, "nopenline: %s, %lu",
  161.                  name,
  162.                  (unsigned long) baud);
  163. #endif
  164.  
  165. /*--------------------------------------------------------------------*/
  166. /*                      Validate the port format                      */
  167. /*--------------------------------------------------------------------*/
  168.  
  169.    if (!equal(name,"CON") && !equaln(name, "COM", 3 ))
  170.    {
  171.       printmsg(0,"nopenline: Communications port begin with COM, was %s",
  172.          name);
  173.       panic();
  174.    }
  175.  
  176. /*--------------------------------------------------------------------*/
  177. /*                          Perform the open                          */
  178. /*--------------------------------------------------------------------*/
  179.  
  180.    hCom = CreateFile( name,
  181.         GENERIC_READ | GENERIC_WRITE,
  182.         0,
  183.         NULL,
  184.         OPEN_EXISTING,
  185.         0,
  186.         NULL);
  187.  
  188. /*--------------------------------------------------------------------*/
  189. /*    Check the open worked.  We translation the common obvious       */
  190. /*    error of file in use to english, for all other errors are we    */
  191. /*    report the raw error code.                                      */
  192. /*--------------------------------------------------------------------*/
  193.  
  194.    if (hCom == INVALID_HANDLE_VALUE) {
  195.        dwError = GetLastError();
  196.        printmsg(0, "nopenline: OpenFile error on port %s", name);
  197.        printNTerror("nopenline", dwError);
  198.        return TRUE;
  199.    }
  200.  
  201. /*--------------------------------------------------------------------*/
  202. /*                    Check for special test mode                     */
  203. /*--------------------------------------------------------------------*/
  204.  
  205.    if ( equal(name,"CON"))
  206.    {
  207.       portActive = TRUE;     /* record status for error handler        */
  208.       carrierdetect = FALSE;  /* Modem is not connected                 */
  209.       console = TRUE;
  210.       return 0;
  211.    }
  212.  
  213.    console = FALSE;
  214.  
  215. /*--------------------------------------------------------------------*/
  216. /*            Reset any errors on the communications port             */
  217. /*--------------------------------------------------------------------*/
  218.  
  219.    rc = ClearCommError (hCom,
  220.         &dwError,
  221.         NULL);
  222.  
  223.    if (!rc) {
  224.       printmsg(0, "nopenline: Error in ClearCommError() call\n");
  225.       printNTerror("nopenline", dwError);
  226.    }
  227.  
  228. /*--------------------------------------------------------------------*/
  229. /*                           Set baud rate                            */
  230. /*--------------------------------------------------------------------*/
  231.  
  232.    SIOSpeed(baud);
  233.  
  234. /*--------------------------------------------------------------------*/
  235. /*                        Set line attributes                         */
  236. /*--------------------------------------------------------------------*/
  237.  
  238. #ifdef UDEBUG
  239.    printmsg(15,"nopenline: Getting attributes");
  240. #endif
  241.  
  242.    rc = GetCommState(hCom, &dcb);
  243.    if (!rc) {
  244.       dwError = GetLastError();
  245.  
  246.       printmsg(0,"nopenline: Unable to get line attributes for %s",name);
  247.       printNTerror("nopenline", dwError);
  248.       panic();
  249.    }
  250.  
  251.    dcb.StopBits = ONESTOPBIT;
  252.    dcb.Parity = NOPARITY;
  253.    dcb.ByteSize = 8;
  254.  
  255. #ifdef UDEBUG
  256.    printmsg(15,"nopenline: Setting attributes");
  257. #endif
  258.  
  259.    rc = SetCommState(hCom, &dcb);
  260.    if (!rc)
  261.    {
  262.       dwError = GetLastError();
  263.  
  264.       printmsg(0,"nopenline: Unable to set line attributes for %s",name);
  265.       printNTerror("nopenline", dwError);
  266.  
  267.       panic();
  268.  
  269.    }
  270.  
  271. /*--------------------------------------------------------------------*/
  272. /*                     Disable XON/XOFF flow control                  */
  273. /*                     Enable CTS handling for flow control           */
  274. /*--------------------------------------------------------------------*/
  275.  
  276. #ifdef UDEBUG
  277.    printmsg(15,"nopenline: Getting flow control information");
  278. #endif
  279.  
  280.    GetCommState(hCom, &dcb);
  281.    dcb.fOutX = 0;
  282.    dcb.fInX = 0;
  283.    dcb.fOutxCtsFlow = 1;
  284.    rc = SetCommState(hCom, &dcb);
  285.    if (!rc) {
  286.       dwError = GetLastError();
  287.       printmsg(0,"nopenline: Unable to set comm attributes for %s",name);
  288.       printNTerror("nopenline", dwError);
  289.  
  290.       panic();
  291.    }
  292.  
  293. /* Get communications timeout information */
  294.  
  295.    rc = GetCommTimeouts(hCom, &CommTimeout);
  296.    if (!rc) {
  297.       dwError = GetLastError();
  298.       printmsg(0, "nopenline: error on GetCommTimeouts() on %s", name);
  299.       printNTerror("nopenline", dwError);
  300.       panic();
  301.    }
  302.  
  303. /*--------------------------------------------------------------------*/
  304. /*                     Raise Data Terminal Ready                      */
  305. /*--------------------------------------------------------------------*/
  306.  
  307.    GetCommState(hCom, &dcb);
  308.    dcb.fDtrControl = DTR_CONTROL_ENABLE;
  309.    dcb.fRtsControl = RTS_CONTROL_ENABLE;
  310.  
  311.    rc = SetCommState(hCom, &dcb);
  312.    if (!rc) {
  313.       printmsg(0,
  314.  
  315.             "nopenline: Unable to raise DTR/RTS for %s",
  316.                   name);
  317.  
  318.       panic();
  319.    }
  320.  
  321.    traceStart( name );     // Enable logging
  322.  
  323.    portActive = TRUE;     /* record status for error handler        */
  324.    carrierdetect = FALSE;  /* Modem is not connected                 */
  325.  
  326. /*--------------------------------------------------------------------*/
  327. /*                     Wait for port to stablize                      */
  328. /*--------------------------------------------------------------------*/
  329.  
  330.    ddelay(500);            /* Allow port to stablize          */
  331.    return 0;
  332.  
  333. } /*openline*/
  334.  
  335. /*--------------------------------------------------------------------*/
  336. /*    n s r e a d                                                     */
  337. /*                                                                    */
  338. /*    Read from the serial port                                       */
  339. /*                                                                    */
  340. /*   Non-blocking read essential to "g" protocol.  See "dcpgpkt.c"    */
  341. /*   for description.                                                 */
  342. /*                                                                    */
  343. /*   This all changes in a multi-tasking system.  Requests for I/O    */
  344. /*   should get queued and an event flag given.  Then the             */
  345. /*   requesting process (e.g. gmachine()) waits for the event flag    */
  346. /*   to fire processing either a read or a write.  Could be           */
  347. /*   implemented on VAX/VMS or DG but not MS-DOS.                     */
  348. /*                                                                    */
  349. /*    OS/2 we could multitask, but we just let the system provide     */
  350. /*    a timeout for us with very little CPU usage.                    */
  351. /*--------------------------------------------------------------------*/
  352.  
  353. unsigned int nsread(char *output, unsigned int wanted, unsigned int timeout)
  354. {
  355.    static LPVOID psave;
  356.    DWORD dwError;
  357.    BOOL rc;
  358.    static char save[MAXPACK];
  359.    static USHORT bufsize = 0;
  360.    time_t stop_time ;
  361.    time_t now ;
  362.  
  363. /*--------------------------------------------------------------------*/
  364. /*           Determine if our internal buffer has the data            */
  365. /*--------------------------------------------------------------------*/
  366.  
  367.    if (bufsize >= wanted)
  368.    {
  369.       memmove( output, save, wanted );
  370.       bufsize -= wanted;
  371.       if ( bufsize )          /* Any data left over?                 */
  372.          memmove( save, &save[wanted], bufsize );  /* Yes --> Save it*/
  373.       return wanted + bufsize;
  374.    } /* if */
  375.  
  376. /*--------------------------------------------------------------------*/
  377. /*            Reset any errors on the communications port             */
  378. /*--------------------------------------------------------------------*/
  379.  
  380.    rc = ClearCommError (hCom,
  381.         &dwError,
  382.         NULL);
  383.  
  384.    if (!rc) {
  385.       printmsg(0, "sread:  Unable to read port errors");
  386.       printNTerror("sread", dwError);
  387.    }
  388.  
  389. /*--------------------------------------------------------------------*/
  390. /*                 Determine when to stop processing                  */
  391. /*--------------------------------------------------------------------*/
  392.  
  393.    if ( timeout == 0 )
  394.    {
  395.       stop_time = 0;
  396.       now = 1;                /* Any number greater than stop time   */
  397.    }
  398.    else {
  399.       time( & now );
  400.       stop_time = now + timeout;
  401.    }
  402.  
  403. /*--------------------------------------------------------------------*/
  404. /*            Try to read any needed data into the buffer             */
  405. /*--------------------------------------------------------------------*/
  406.  
  407.    do {
  408.       DWORD received;
  409.       DWORD needed = wanted - bufsize;
  410.       DWORD port_timeout;
  411.  
  412. /*--------------------------------------------------------------------*/
  413. /*                     Handle an aborted program                      */
  414. /*--------------------------------------------------------------------*/
  415.  
  416.       if ( terminate_processing )
  417.       {
  418.          static boolean recurse = FALSE;
  419.          if ( ! recurse )
  420.          {
  421.             printmsg(2,"sread: User aborted processing");
  422.             recurse = TRUE;
  423.          }
  424.          return 0;
  425.       }
  426.  
  427. /*--------------------------------------------------------------------*/
  428. /*           Compute a new timeout for the read, if needed            */
  429. /*--------------------------------------------------------------------*/
  430.  
  431.       if (stop_time > now )
  432.       {
  433.          port_timeout = (USHORT) (stop_time - now) / needed * 100;
  434.          if (port_timeout < 100)
  435.             port_timeout = 100;
  436.       }
  437.       else
  438.          port_timeout = 0;
  439.  
  440.       if (!console)
  441.       {
  442.           port_timeout *= 10; /* OS/2 is in hundredths; NT in msec */
  443.           CommTimeout.ReadTotalTimeoutConstant = 0;
  444.           CommTimeout.WriteTotalTimeoutConstant = 0;
  445.           CommTimeout.ReadIntervalTimeout = port_timeout;
  446.           CommTimeout.ReadTotalTimeoutMultiplier = 1;
  447.           CommTimeout.WriteTotalTimeoutMultiplier = 0;
  448.           rc = SetCommTimeouts(hCom, &CommTimeout);
  449.  
  450.           if ( !rc )
  451.           {
  452.              dwError = GetLastError();
  453.              printmsg(0, "sread: unable to set timeout for comm port");
  454.              printNTerror("sread", dwError);
  455.              panic();
  456.           }
  457.       }
  458.  
  459. #ifdef UDEBUG
  460.       printmsg(15,"sread: Port time out is %ud seconds/100",
  461.                port_timeout);
  462. #endif
  463.  
  464. /*--------------------------------------------------------------------*/
  465. /*                 Read the data from the serial port                 */
  466. /*--------------------------------------------------------------------*/
  467.  
  468.       rc = ReadFile (hCom, &save[bufsize], needed, &received, NULL);
  469.  
  470.       if (!rc) {
  471.          printmsg(0,
  472.             "sread: Read from comm port for %d bytes failed, received = %d.",
  473.             needed, received);
  474.          bufsize = 0;
  475.          return 0;
  476.       }
  477.  
  478. #ifdef UDEBUG
  479.       printmsg(15,"sread: Want %d characters, received %d, total %d in buffer",
  480.             (int) wanted, (int) received, (int) bufsize + received);
  481. #endif
  482.  
  483. /*--------------------------------------------------------------------*/
  484. /*                    Log the newly received data                     */
  485. /*--------------------------------------------------------------------*/
  486.  
  487.       traceData( &save[bufsize], received, FALSE );
  488.  
  489. /*--------------------------------------------------------------------*/
  490. /*            If we got the data, return it to the caller             */
  491. /*--------------------------------------------------------------------*/
  492.  
  493.       bufsize += received;
  494.       if ( bufsize == wanted )
  495.       {
  496.          memmove( output, save, bufsize);
  497.          bufsize = 0;
  498.  
  499.          if (debuglevel > 14)
  500.             fwrite(output,1,bufsize,stdout);
  501.  
  502.          return wanted;
  503.       } /* if */
  504.  
  505. /*--------------------------------------------------------------------*/
  506. /*                 Update the clock for the next pass                 */
  507. /*--------------------------------------------------------------------*/
  508.  
  509.       if (stop_time > 0)
  510.          time( &now );
  511.  
  512.    } while (stop_time > now);
  513.  
  514. /*--------------------------------------------------------------------*/
  515. /*         We don't have enough data; report what we do have          */
  516. /*--------------------------------------------------------------------*/
  517.  
  518.    return bufsize;
  519.  
  520. } /*nsread*/
  521.  
  522. /*--------------------------------------------------------------------*/
  523. /*    n s w r i t e                                                   */
  524. /*                                                                    */
  525. /*    Write to the serial port                                        */
  526. /*--------------------------------------------------------------------*/
  527.  
  528. int nswrite(const char *input, unsigned int len)
  529. {
  530.  
  531.    char *data = (char *) input;
  532.  
  533.    DWORD bytes;
  534.    BOOL rc;
  535.    hangupNeeded = TRUE;      /* Flag that the port is now dirty  */
  536.  
  537. /*--------------------------------------------------------------------*/
  538. /*         Write the data out as the queue becomes available          */
  539. /*--------------------------------------------------------------------*/
  540.  
  541.    rc = WriteFile (hCom, data, len, &bytes, NULL);
  542.  
  543.    if (!rc) {
  544.       printmsg(0,"swrite: Write to communications port failed.");
  545.  
  546.       return bytes;
  547.    }
  548.  
  549. /*--------------------------------------------------------------------*/
  550. /*                        Log the data written                        */
  551. /*--------------------------------------------------------------------*/
  552.  
  553.    traceData( data, len, TRUE);
  554.  
  555. /*--------------------------------------------------------------------*/
  556. /*            Return bytes written to the port to the caller          */
  557. /*--------------------------------------------------------------------*/
  558.  
  559.    return len;
  560.  
  561. } /*nswrite*/
  562.  
  563. /*--------------------------------------------------------------------*/
  564. /*    n s s e n d b r k                                               */
  565. /*                                                                    */
  566. /*    send a break signal out the serial port                         */
  567. /*--------------------------------------------------------------------*/
  568.  
  569. void nssendbrk(unsigned int duration)
  570. {
  571.  
  572. #ifdef UDEBUG
  573.    printmsg(12, "ssendbrk: %d", duration);
  574. #endif
  575.  
  576.    SetCommBreak(hCom);
  577.  
  578.    ddelay( duration == 0 ? 200 : duration);
  579.  
  580.    ClearCommBreak(hCom);
  581.  
  582. } /*nssendbrk*/
  583.  
  584. /*--------------------------------------------------------------------*/
  585. /*    n c l o s e l i n e                                             */
  586. /*                                                                    */
  587. /*    Close the serial port down                                      */
  588. /*--------------------------------------------------------------------*/
  589.  
  590. void ncloseline(void)
  591. {
  592.    DWORD dwError;
  593.  
  594.    if ( ! portActive )
  595.       panic();
  596.  
  597.    portActive = FALSE; /* flag port closed for error handler  */
  598.    hangupNeeded = FALSE;  /* Don't fiddle with port any more  */
  599.  
  600. /*--------------------------------------------------------------------*/
  601. /*                             Lower DTR                              */
  602. /*--------------------------------------------------------------------*/
  603.  
  604.    if (!EscapeCommFunction(hCom, CLRDTR | CLRRTS))
  605.    {
  606.       printmsg(0,"ncloseline: Unable to lower DTR/RTS");
  607.    }
  608.  
  609. /*--------------------------------------------------------------------*/
  610. /*                      Actually close the port                       */
  611. /*--------------------------------------------------------------------*/
  612.  
  613.    if(!CloseHandle(hCom))
  614.    {
  615.       dwError = GetLastError();
  616.       printmsg(0, "ncloseline: close of serial port failed");
  617.       printNTerror("ncloseline", dwError);
  618.    }
  619.  
  620. /*--------------------------------------------------------------------*/
  621. /*                   Stop logging the data to disk                    */
  622. /*--------------------------------------------------------------------*/
  623.  
  624.    traceStop();
  625.  
  626. } /* ncloseline */
  627.  
  628. /*--------------------------------------------------------------------*/
  629. /*    n h a n g u p                                                   */
  630. /*                                                                    */
  631. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  632. /*    many compatibles.                                               */
  633. /*    14 May 89 Drew Derbyshire                                       */
  634. /*--------------------------------------------------------------------*/
  635.  
  636. void nhangup( void )
  637. {
  638.    if (!hangupNeeded)
  639.       return;
  640.  
  641.    hangupNeeded = FALSE;
  642.  
  643.    if ( console )
  644.       return;
  645.  
  646. /*--------------------------------------------------------------------*/
  647. /*                              Drop DTR                              */
  648. /*--------------------------------------------------------------------*/
  649.  
  650.    if (!EscapeCommFunction(hCom, CLRDTR))
  651.    {
  652.       printmsg(0, "hangup: Unable to lower DTR for comm port");
  653.       panic();
  654.    }
  655.  
  656. /*--------------------------------------------------------------------*/
  657. /*                  Wait for the telephone to hangup                  */
  658. /*--------------------------------------------------------------------*/
  659.  
  660.    printmsg(3,"hangup: Dropped DTR");
  661.    carrierdetect = FALSE;  /* Modem is not connected                 */
  662.    ddelay(500);            /* Really only need 250 milliseconds         */
  663.  
  664. /*--------------------------------------------------------------------*/
  665. /*                          Bring DTR back up                         */
  666. /*--------------------------------------------------------------------*/
  667.  
  668.    if (!EscapeCommFunction(hCom, SETDTR))
  669.    {
  670.       printmsg(0, "hangup: Unable to raise DTR for comm port");
  671.       panic();
  672.    }
  673.  
  674.    ddelay(2000);           /* Now wait for the poor thing to recover    */
  675.  
  676. } /* nhangup */
  677.  
  678. /*--------------------------------------------------------------------*/
  679. /*    n S I O S p e e d                                               */
  680. /*                                                                    */
  681. /*    Re-specify the speed of an opened serial port                   */
  682. /*                                                                    */
  683. /*    Dropped the DTR off/on calls because this makes a Hayes drop    */
  684. /*    the line if configured properly, and we don't want the modem    */
  685. /*    to drop the phone on the floor if we are performing             */
  686. /*    autobaud.                                                       */
  687. /*                                                                    */
  688. /*    (Configured properly = standard method of making a Hayes        */
  689. /*    hang up the telephone, especially when you can't get it into    */
  690. /*    command state because it is at the wrong speed or whatever.)    */
  691. /*--------------------------------------------------------------------*/
  692.  
  693. void nSIOSpeed(BPS baud)
  694. {
  695.    USHORT rc;
  696.  
  697. #ifdef UDEBUG
  698.    printmsg(15,"SIOSpeed: Setting baud rate to %lu",
  699.                (unsigned long) baud);
  700. #endif
  701.  
  702.    GetCommState (hCom, &dcb);
  703.    dcb.BaudRate = baud;
  704.    rc = SetCommState (hCom, &dcb);
  705.    if (!rc && !console) {
  706.       printmsg(0,"SIOSpeed: Unable to set baud rate for port to %lu",
  707.                   (unsigned long) baud);
  708.       panic();
  709.  
  710.    }
  711.  
  712.    currentSpeed = baud;
  713.  
  714. } /* nSIOSpeed */
  715.  
  716. /*--------------------------------------------------------------------*/
  717. /*    n f l o w c o n t r o l                                         */
  718. /*                                                                    */
  719. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  720. /*--------------------------------------------------------------------*/
  721.  
  722. void nflowcontrol( boolean flow )
  723. {
  724.    USHORT rc;
  725.    DCB dcb;
  726.    DWORD dwError;
  727.  
  728.    if ( console )
  729.       return;
  730.  
  731.    GetCommState(hCom, &dcb);
  732.    if (flow)
  733.    {
  734.       dcb.fOutX = TRUE;
  735.       dcb.fInX = TRUE;
  736.       dcb.fRtsControl = RTS_CONTROL_ENABLE;
  737.       dcb.fOutxCtsFlow = FALSE;
  738.    } else {
  739.       dcb.fOutX = FALSE;
  740.       dcb.fInX = FALSE;
  741.       dcb.fRtsControl = RTS_CONTROL_ENABLE;
  742.       dcb.fOutxCtsFlow = TRUE;
  743.    }
  744.    rc = SetCommState(hCom, &dcb);
  745.  
  746.    if ( !rc )
  747.    {
  748.       dwError = GetLastError();
  749.  
  750.       printmsg(0,"flowcontrol: Unable to set flow control");
  751.       printNTerror("nflowcontrol", dwError);
  752.  
  753.       panic();
  754.  
  755.    } /*if */
  756.  
  757. } /* nflowcontrol */
  758.  
  759. /*--------------------------------------------------------------------*/
  760. /*    n G e t S p e e d                                               */
  761. /*                                                                    */
  762. /*    Report current speed of communications connection               */
  763. /*--------------------------------------------------------------------*/
  764.  
  765. BPS nGetSpeed( void )
  766. {
  767.    return currentSpeed;
  768. } /* nGetSpeed */
  769.  
  770. /*--------------------------------------------------------------------*/
  771. /*   n C D                                                            */
  772. /*                                                                    */
  773. /*   Return status of carrier detect                                  */
  774. /*--------------------------------------------------------------------*/
  775.  
  776. boolean nCD( void )
  777. {
  778.    boolean previous_carrierdetect = carrierdetect;
  779.    USHORT rc;
  780.  
  781.    DWORD status;
  782.    static DWORD oldstatus = (DWORD) 0xDEADBEEF;
  783.    DWORD dwError;
  784.  
  785.    if ( console )
  786.       return feof( stdin ) == 0;
  787.  
  788.    rc = GetCommModemStatus(hCom, &status);
  789.    if ( !rc )
  790.    {
  791.       dwError = GetLastError();
  792.       printmsg(0,"nCD: Unable to get modem status");
  793.       printNTerror("nCD", dwError);
  794.       panic();
  795.    } /*if */
  796.  
  797.    if ( status != oldstatus )
  798.    {
  799.       ShowModem( status );
  800.       oldstatus = status;
  801.    }
  802.  
  803. /*--------------------------------------------------------------------*/
  804. /*    If we previously had carrier detect but have lost it, we        */
  805. /*    report it was lost.  If we do not yet have carrier detect,      */
  806. /*    we return success because we may not have connected yet.        */
  807. /*--------------------------------------------------------------------*/
  808.  
  809.    carrierdetect = status && MS_RLSD_ON;
  810.  
  811.    if (previous_carrierdetect)
  812.       return (status && (MS_RLSD_ON || MS_DSR_ON)) ==
  813.                         (MS_RLSD_ON || MS_DSR_ON);
  814.    else
  815.       return (status && MS_DSR_ON);
  816.  
  817. } /* nCD */
  818.  
  819. /*--------------------------------------------------------------------*/
  820. /*    S h o w M o d e m                                               */
  821. /*                                                                    */
  822. /*    Report current modem status                                     */
  823. /*--------------------------------------------------------------------*/
  824.  
  825. #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
  826.  
  827. static void ShowModem( const DWORD status )
  828. {
  829.    if ( debuglevel < 4 )
  830.       return;
  831.  
  832.    printmsg(0, "ShowModem: %#02x%s%s%s%s",
  833.       status,
  834.       mannounce(MS_RLSD_ON,  status, "  Carrier Detect"),
  835.       mannounce(MS_RING_ON,  status, "  Ring Indicator"),
  836.       mannounce(MS_DSR_ON,   status, "  Data Set Ready"),
  837.       mannounce(MS_CTS_ON,   status, "  Clear to Send"));
  838.  
  839. } /* ShowModem */
  840.